﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CosiNet.VM
{
    /// <summary>
    /// Class to provide virtual RAM and methods for managing it.
    /// </summary>
    public class RAM
    {
        /// <summary>
        /// Create a new instance of Virtual RAM for use by the VM.
        /// </summary>
        /// <param name="size">Size in bytes of the RAM</param>
        public RAM(int size)
        {
            memory = new byte[size];
        }

        /// <summary>
        /// The position of the memory one above where the application exists.
        /// </summary>
        public int setLimit;

        /// <summary>
        /// Set a byte in memory.
        /// </summary>
        /// <param name="location">Location in memory to change.</param>
        /// <param name="content">Byte to place in the memory</param>
        public void SetByte(int location, byte content)
        {
            if (location > setLimit)
            {
                memory[location] = content;
            }
            else
            {
                throw new Exception("The application tried to modify itself and was terminated. Consult the application vendor for more support.");
            }
        }

        /// <summary>
        /// Gets a section of memory.
        /// </summary>
        /// <param name="location">The location in memory to start reading from.</param>
        /// <param name="length">The length of the memory to read in bytes.</param>
        /// <returns></returns>
        public byte[] GetSection(int location, int length)
        {
            byte[] ret = new byte[length];
            for (int i = 0; i < length; i++)
            {
                ret[i] = memory[(location + i)];
            }
            return ret;
        }
        /// <summary>
        /// Sets a section of memory
        /// </summary>
        /// <param name="location">The location in memory to start writing into</param>
        /// <param name="content">The content to write</param>
        public void SetSection(int location, byte[] content)
        {
            for (int i = 0; i < content.Length; i++)
            {
                memory[(i + location)] = content[i];
            }
        }

        /// <summary>
        /// The raw VRAM, "should" only be set using SetByte() and should remain read-only from outside processes. Use may result in an OutOfRange Exception.
        /// </summary>
        public byte[] memory;
    }
}
